package com.bdqn.controller;

import com.alibaba.fastjson2.JSONObject;
import com.bdqn.pojo.SysRole;
import com.bdqn.pojo.SysUser;
import com.bdqn.service.SysRoleService;
import com.bdqn.service.SysUserService;
import com.bdqn.util.Constants;
import com.bdqn.util.Page;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.math.RandomUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 系统用户控制器
 *
 * @author LILIBO
 * @since 2024/7/30
 */
@Controller
@RequestMapping("/user") // 统一请求前缀
public class SysUserController {

    private final Logger log = LogManager.getLogger(SysUserController.class);

    @Resource
    private SysRoleService sysRoleService;

    @Resource
    private SysUserService sysUserService;

    /**
     * 分页查询列表数据
     */
    @GetMapping("/list")
    public String list(Model model, @RequestParam(value = "queryRealName", required = false) String queryRealName, @RequestParam(value = "queryRoleId", required = false) Long queryRoleId, @RequestParam(value = "pageIndex", required = false, defaultValue = "1") Long pageIndex) {

        // ① 查询角色列表填充下拉框
        List<SysRole> roleList = sysRoleService.list();

        // ② 查询符合条件的总用户数
        Long count = sysUserService.count(queryRealName, queryRoleId);

        // ③ 根据搜索条件查询分页数据
        Page<SysUser> page = new Page<>();
        page.setPageSize(5L);
        page.setTotalCount(count); // 总数据量在计算当前页数容错处理时需要用到，所以先设置
        page.setCurrentPageNo(pageIndex);
        List<SysUser> list = sysUserService.page(queryRealName, queryRoleId, page);
        page.setData(list);

        // ④ 设置作用域
        model.addAttribute("queryRealName", queryRealName); // 用户填写的查询内容
        model.addAttribute("queryRoleId", queryRoleId); // 用户选择的下拉项
        model.addAttribute("roleList", roleList); // 下拉框列表
        model.addAttribute("page", page); // 查到的分页数据

        // ⑤ 跳转页面
        return "sysUser/list";
    }

    /**
     * 去添加页面
     */
    @GetMapping("/add")
    public String toAdd(Model model) {
        // ① 查询角色列表填充下拉框
        List<SysRole> roleList = sysRoleService.list();
        model.addAttribute("roleList", roleList);
        return "sysUser/add";
    }

    /*
     * 去添加页面（Spring验证）
     */
    /* @GetMapping("/add")
    public String toAdd(Model model, @ModelAttribute("sysUser") SysUser sysUser) {
        // ① 查询角色列表填充下拉框
        List<SysRole> roleList = sysRoleService.list();
        model.addAttribute("roleList", roleList);
        return "sysUser/add";
    } */

    /**
     * Ajax验证账号是否存在
     *
     * @param account 账号
     * @return JSON格式 {"exist":1} 说明：1表示账号已存在；0表示账号不存在；-1表示出错
     */
    @ResponseBody // 直接将数据返回（Ajax请求）
    @GetMapping("/exist")
    public String exist(String account) {
        int exist = -1;
        try {
            // 调用业务逻辑层完成判断
            boolean flag = sysUserService.exist(account);
            if (flag) { // 账号已存在
                exist = 1;
            } else { // 账号不存在
                exist = 0;
            }
        } catch (RuntimeException e) {
            exist = -1;
        }
        // 将数据封装为JSON格式返回
        return JSONObject.of("exist", exist).toString();
    }

    /**
     * 添加用户
     */
    @PostMapping("/add")
    public String doAdd(Model model, HttpServletRequest request, HttpSession session, SysUser sysUser, MultipartFile idPic, MultipartFile workPic) {
        SysUser loginUser = (SysUser) session.getAttribute(Constants.USER_SESSION);
        sysUser.setCreatedUserId(loginUser.getId());
        sysUser.setCreatedTime(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));

        // 文件上传到服务器的真实位置 C:\Service\apache-tomcat-9.0.91\webapps\724\web\statics\...
        String uploadPath = session.getServletContext().getRealPath(Constants.UPLOAD_PATH);

        Map<String, String> msg = new HashMap<>();
        // 身份证照片上传
        if (idPic != null) {
            // 提取文件上传的方法
            String idPicPath = multipartFileUpload(uploadPath, idPic, msg);
            // Web访问的路径（不是文件上传的磁盘位置）
            if (idPicPath == null) {
                String uploadFileError = msg.get("uploadFileError");
                request.setAttribute("idPicUploadError", uploadFileError);
                return "sysUser/add";
            }
            // 设置身份证照片路径
            sysUser.setIdPicPath(idPicPath);
        }
        // 工作证照片上传
        if (workPic != null) {
            // 提取文件上传的方法
            String workPicPath = multipartFileUpload(uploadPath, workPic, msg);
            // Web访问的路径（不是文件上传的磁盘位置）
            if (workPicPath == null) {
                String uploadFileError = msg.get("uploadFileError");
                request.setAttribute("workPicUploadError", uploadFileError);
                return "sysUser/add";
            }
            // 设置工作证照片路径
            sysUser.setWorkPicPath(workPicPath);
        }

        // 调用业务逻辑层完成用户添加
        boolean flag = sysUserService.add(sysUser);
        if (flag) { // 成功重定向到列表页
            return "redirect:/user/list";
        }
        return "sysUser/add";
    }

    /**
     * 多部件文件上传（错误信息临时保存在request作用域uploadFileError属性中）
     *
     * @return 成功返回文件上传地址，返回null表示文件上传失败
     */
    public synchronized String multipartFileUpload(String uploadPath, MultipartFile multipartFile, Map<String, String> msg) {
        String uploadFilePath = null; // 文件上传地址，返回null表示文件上传失败

        // 定义文件存放目录
        log.debug("上传文件路径：" + uploadPath);

        if (!multipartFile.isEmpty()) {
            // 获取上传的文件信息
            String originalFile = multipartFile.getOriginalFilename(); // 原文件名称
            log.debug("原文件名称为：" + originalFile);
            String prefix = FilenameUtils.getExtension(originalFile); // 原文件后缀
            log.debug("原文件后缀为：" + prefix);
            long fileSize = multipartFile.getSize(); // 原文件大小
            log.debug("上传文件大小：" + fileSize);

            // 判断上传的文件是否符合要求
            if (fileSize > Constants.MAX_FILE_SIZE) { // 上传文件大小不能超过500KB
                msg.put("uploadFileError", " * 上传文件大小不得超过 5MB");
                return uploadFilePath;
            }
            if (prefix != null && !(prefix.equalsIgnoreCase("jpg") || prefix.equalsIgnoreCase("jpeg") || prefix.equalsIgnoreCase("png") || prefix.equalsIgnoreCase("pneg"))) {
                msg.put("uploadFileError", " * 上传文件格式只能是jpg、jpeg、png、pneg");
                return uploadFilePath;
            }

            // 确定文件存储名称
            String fileName = System.nanoTime() + RandomUtils.nextInt(1000) + "_Personal." + prefix;
            log.debug("新生成的文件名为：" + fileName);

            // 将上传的文件保存到目标位置
            File targetFile = new File(uploadPath);
            if (!targetFile.exists()) {
                targetFile.mkdirs(); // 如果目录不存在则生成目录
            }
            // 保存文件
            try {
                // 存储物理地址 + 生成的文件名称
                multipartFile.transferTo(new File(targetFile, fileName));
            } catch (IOException e) {
                e.printStackTrace();
                msg.put("uploadFileError", " * 文件上传失败！");
                return uploadFilePath;
            }
            // 文件上传完成就可以拿到地址
            // /statics/upload/98020913201542_Personal.jpg
            uploadFilePath = "/" + Constants.UPLOAD_PATH + "/" + fileName;
        }

        // 返回文件上传成功后的地址，失败时返回null，并且将失败信息记录到
        return uploadFilePath;
    }

    /*
     * 添加用户（Spring验证，BindingResult参数需要紧接着@Valid注解，否则Spring在效验不通过时直接抛出异常）
     */
    /* @PostMapping("/add")
    public String doAdd(@Valid SysUser sysUser, BindingResult bindingResult, Model model, HttpSession session) {
        // 如果有非法项
        if (bindingResult.hasErrors()) {
            log.debug("添加用户验证失败！");
            return "sysUser/add"; // 可以将错误信息带回去
        }

        SysUser loginUser = (SysUser) session.getAttribute(Constants.USER_SESSION);
        sysUser.setCreatedUserId(loginUser.getId());
        sysUser.setCreatedTime(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        boolean flag = sysUserService.add(sysUser);
        if (flag) { // 成功重定向到列表页
            return "redirect:/user/list";
        }
        model.addAttribute("error", "添加失败！");
        return "sysUser/add";
    } */

    /**
     * Ajax查询数据展示
     *
     * @param userId 用户ID
     * @return JSON格式的对象数据
     */
    @ResponseBody
    @GetMapping("/{userId}/view")
    public String view(@PathVariable("userId") Long userId) {
        // 调用业务逻辑层根据ID查询用户
        SysUser sysUser = sysUserService.getById(userId);
        return JSONObject.toJSONString(sysUser);
    }

    /**
     * Ajax异步删除用户
     *
     * @param userId
     * @return
     */
    @ResponseBody
    @DeleteMapping("/del/{userId}")
    public String del(HttpSession session, @PathVariable("userId") Long userId) {
        String uploadPath = session.getServletContext().getRealPath(Constants.UPLOAD_PATH);
        int result = 0;
        try {
            result = sysUserService.del(uploadPath, userId); // -1表示不存在，1表示成功，0表示失败
        } catch (RuntimeException e) {
            result = 0;
            log.error(e.getMessage());
        }
        return JSONObject.of("delResult", result == -1 ? "notexist" : result == 1 ? "true" : "false").toString();
    }

    /**
     * Ajax查询用户的密码是否正确
     *
     * @param oldPwd 用户旧密码
     * @return JSON格式的对象数据
     */
    @ResponseBody
    @PostMapping("/checkOldPwd")
    public String checkOldPwd(HttpSession session, String oldPwd) {
        // 判断Session是否过期
        if (session != null && !session.isNew()) {
            long lastAccessedTime = session.getLastAccessedTime();
            int maxInactiveInterval = session.getMaxInactiveInterval();
            long now = System.currentTimeMillis();
            if (now - lastAccessedTime > maxInactiveInterval * 1000) {
                return JSONObject.of("result", "sessionerror").toString();
            }
        }
        SysUser loginUser = (SysUser) session.getAttribute(Constants.USER_SESSION);
        if (oldPwd != null && oldPwd.equals(loginUser.getPassword())) {
            return JSONObject.of("result", "true").toString();
        } else {
            return JSONObject.of("result", "false").toString();
        }
    }

}
